﻿
using System;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Windows.Controls.Primitives;
using System.Device.Location;
using Microsoft.Phone.Controls.Maps;
using OttawaTourMap.Helpers;
using Microsoft.Phone.Controls.Maps.Platform;
using OttawaTourMap.Models;
using System.Windows.Threading;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Linq;
using System.Collections.ObjectModel;
using System.Windows.Navigation;
using Expression.Blend.SampleData.ottawaSampleDataSource;

namespace OttawaTourMap
{
    //TODO : Imp - we need to create the pushpin programatically to gain more control over them.
    /// <summary>
    /// This partial class contains startup code for implementing the bing maps lab,
    /// so you can concentrate on the Bing map control and services and not on the
    /// UI behavior or application flow.
    /// <remarks>
    /// User code should be added to the MainPage.xaml.cs file only.
    /// </remarks>
    public partial class MainPage : INotifyPropertyChanged
    {
        #region Fields

        /// <value>Helper for handling mouse (touch) events.</value>
        private readonly TouchBehavior _touchBehavior;

        /// <value>Helper for handling visual states.</value>
        private readonly VisualStates _visualStates;

        #endregion

        #region Ctor
        
        public MainPage()
        {
            InitializeDefaults();
            InitializeComponent();

           

            _touchBehavior = new TouchBehavior(this);
            _touchBehavior.Tap += touchBehavior_Tap;
            _touchBehavior.Move += touchBehavior_Move;
            _touchBehavior.Hold += touchBehavior_Hold;

            _visualStates = new VisualStates(this);

            DataContext = this;

                        // Delcare GeoCoordinateWatcher with high accuracy
            // in order to use the device's GPS
            _geoCoordinateWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
            _geoCoordinateWatcher.MovementThreshold = 10; // 10mts 
            
            // Subscribe to the device's status changed event
            _geoCoordinateWatcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(_geoCoordinateWatcher_StatusChanged);
           
            // Subscribe to the device's position changed event
            // to receive GPS coordinates (longitude and latitude)
            _geoCoordinateWatcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(_geoCoordinateWatcher_PositionChanged);

            //if (!_geoCoordinateWatcher.TryStart(true, TimeSpan.FromSeconds(5)))
           // {
            //    MessageBox.Show("Please enable Location Service on the Phone.",
            //    "Warning", MessageBoxButton.OK);
           // }
            _geoCoordinateWatcher.Start();

            getSampleData();
            //Call Simulator code
            startSimulation();





            //add code to simulate this

            // Place the user push pin to the default location
            userLocationPushPin.Location = DefaultLocation;
            BlinkLocator.Begin();
           
        }

        #region GPSSImulator_code

        List<string> lat = new List<string>();
        List<string> lon = new List<string>();

        public void getSampleData()
        {
             XDocument xdoc = XDocument.Load("TourData\\sampleTourPoints.xml");
             var toursListElement = xdoc.Elements("routes");

             lat = (from tour in toursListElement.Elements("route")
                                   select tour.Attribute("lat").Value.ToString()).ToList<string>();


            lon = (from tour in toursListElement.Elements("route")
                                 select tour.Attribute("lon").Value.ToString()).ToList<string>();
        }

      
        //adjust how many meters before the 'beyond threshold' call is triggered
        const int THRESHOLD = 1; 
        //Create the client to consume the WCF data
       // ServiceReference1.GPSSimClient client = new ServiceReference1.GPSSimClient();

        //this timer will determine how often the readings should be downloaded
        DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
        /// <summary>
        /// 
        /// GPS Simulator
        /// </summary>
        private void startSimulation()
        {
            //assign the event handler to the tick event
            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);

            //choose how often should the readings be taken
            dispatcherTimer.Interval = new TimeSpan(0,0,1);

            //what to do when the reading has been taken (don't forget, all Silverlight calls are ASync, so you need to handle
            //the completed event to get the result
           // client.GetGPSDataCompleted += new EventHandler<ServiceReference1.GetGPSDataCompletedEventArgs>(client_GetGPSDataCompleted);

            //start the timer
            dispatcherTimer.Start();
        }

        int sampelDataIndex = 0;
        void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            //if the user has started the reading
           
                //download the reading whenever the interval is called
                //client.GetGPSDataAsync();
            double latitude = double.Parse(lat.ElementAt(sampelDataIndex));
            double longitude = double.Parse(lon.ElementAt(sampelDataIndex));
            SetLocation(latitude,longitude, 18/* Zoom level*/, true);
            sampelDataIndex++;

            if (sampelDataIndex >= lat.Count())
            {
                dispatcherTimer.Stop();
            }

            //just stop after first count
           // dispatcherTimer.Stop();

        }
        /*
        void client_GetGPSDataCompleted(object sender, ServiceReference1.GetGPSDataCompletedEventArgs e)
        {
            //get the result
            var data = e.Result;

            if (CheckThreshold( data[0], data[1]))
            {
                SetLocation(data[0],
                data[1], 18, true);
            }
        }
*/
        public bool CheckThreshold(double nLat,double nLon)
        {
            GeoCoordinate userLocation = new GeoCoordinate(UserCurrentLocationLatitude, UserCurrentLocationLongitude);

            GeoCoordinate tourLocation = new GeoCoordinate(nLat, nLon);
            double tempDist = userLocation.GetDistanceTo(tourLocation);

            if (tempDist > THRESHOLD)
            {
                return true;
            }
            else return false;
            /*
            //thanks to code found here (http://forums.silverlight.net/forums/p/191064/441241.aspx#441241)
            clon *= Math.PI / 180;
            clat *= Math.PI / 180;
            var dstLongR = nLon * Math.PI / 180;
            var dstLatR = nLat * Math.PI / 180;
            var earthRadius = 3958.75587;
            var distance = Math.Acos(Math.Sin(clat) * Math.Sin(dstLatR) +
                        Math.Cos(clat) * Math.Cos(dstLatR) * Math.Cos((dstLongR - clat))) * earthRadius;
            distance = Math.Floor(distance * 10) / 10;


            //convert miles to meters since WP7 emulator has meters threshold, so probably more useful :)
            double meters = distance * 1609.344;


            //assign the old values as the current value, so in the next loop it represents the previous value
            oldLat = nLat;
            oldLon = nLon;


            //if the distance travelled is greater than the threshold return true, otherwise return false
            if (Math.Abs(meters - oldMeters) > THRESHOLD)
            {
                oldMeters = meters;
                return true;
            }
            else
            {
                oldMeters = meters;
                return false;
            }

             * 
             */


        }
        #endregion GPSSImulator_code

        #endregion

        #region Event Handlers

        private void _geoCoordinateWatcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => ChangePosition(e));
        }
        private void ChangePosition(GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            
            SetLocation(e.Position.Location.Latitude,
            e.Position.Location.Longitude, 18/* Zoom level*/, true);
        }
        private void _geoCoordinateWatcher_StatusChanged(object sender,
        GeoPositionStatusChangedEventArgs e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => StatusChanged(e));
        }

        //TODO : Handle the status change event
        private void StatusChanged(GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:
                   // txtStatus.Text = "Location Service is disabled!";
                    break;
                case GeoPositionStatus.Initializing:
                   // txtStatus.Text = "Initializing Location Service...";
                    break;
                case GeoPositionStatus.NoData:
                   // txtStatus.Text = "Your position could not be located.";
                    break;
                case GeoPositionStatus.Ready:
                    break;
            }
        }

        private void SetLocation(double latitude, double longitude, double zoomLevel, bool showLocator)
        {
            // Move the user push pin to this location
            //set the default location
            setDefaultLocation(new GeoCoordinate(latitude, longitude));
            userLocationPushPin.Location = DefaultLocation;

           
            //set the user location
            UserCurrentLocationLatitude = latitude;
            UserCurrentLocationLongitude = longitude;

            trackUserMovement();

            if (FollowUser)
            {
                //traceUserRoute.Add(new UserTraceModel(DefaultLocation));
            }
        }

        private void ButtonLocation_Click(object sender, EventArgs e)
        {
            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;

            CenterLocation();
        }

        private Pushpin selectedPushPin = null;
        RouteViewDataContext rotueViewDataContext = new RouteViewDataContext();
        private void Pushpin_MouseLeftButtonUp(object sender, EventArgs e)
        {
           
            selectedPushPin = sender as Pushpin;
            
            if(selectedPushPin == null) return;

            TextBlock content = selectedPushPin.Content as TextBlock;

            stopIndex = int.Parse(content.Text);
            stopIndex = stopIndex - 1; // since the first pushpin is user's location

            if (stopIndex < 0)
            {

                return; // As this is users location
            }

            if (_visualStates.RouteState == VisualStates.HideRoute)
            {
                _visualStates.RouteState = VisualStates.ShowRoute;
            }

           //TODO: Change the stop index to stop id
            stop stop = selectedTour.stopCollection[stopIndex];
            
            //Since we dont have mandatory image tag in stop, we will display any image from any random point of interest from the stop
            pointOfInterest pointofInterest = stop.pointOfInterestCollection[0];
            rotueViewDataContext.ThumbNailUri = pointofInterest.ThumbNailURI;
            rotueViewDataContext.Text = stop.title;

            Grid routeView = RouteView.Child as Grid;
            routeView.DataContext = rotueViewDataContext;

        }

        

        private void ButtonRoute_Click(object sender, EventArgs e)
        {
            //Naviagate Back to the previous menu page.
            //NavigationService.GoBack();
            NavigationService.Navigate(new Uri("/ToursListPage.xaml", UriKind.Relative));

            // Display or hide route panel.
           /* if (_visualStates.RouteState == VisualStates.HideRoute)
            {
                _visualStates.RouteState = VisualStates.ShowRoute;
            }
            else
            {
                _visualStates.RouteState = VisualStates.HideRoute;
            }

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
            * 
            */
        }


        private void ButtonToggleRoute_Click(object sender, EventArgs e)
        {
            return;

            //TODO : To implement this 
            /*
            toggleCompleteTour = !toggleCompleteTour;

            // Clear the route collection to have only one route at a time.
            Routes.Clear();

            // Clear previous route related itineraries.
            Itineraries.Clear();

            RouteModel routeModel;
            
            //Toggle from complete version to short version
            if (toggleCompleteTour)
            {
                //Check whether the route has already been calculated
                if (shortTourResult != null)
                {// Create a new route based on route calculator result,
                    // and add the new route to the route collection.
                    routeModel = new RouteModel(shortTourResult.routePoints);
                    // Add new route itineraries to the itineraries collection.
                    foreach (var itineraryItem in shortTourResult.routeItenaries[0].Itinerary)
                    {
                        Itineraries.Add(itineraryItem);
                    }

                    Routes.Add(routeModel);
                    // Set the map to center on the new route.
                    //TODO : Change this to point to the start location of the tour
                    var viewRect = LocationRect.CreateLocationRect(routeModel.Locations);
                    Map.SetView(viewRect);

                    //ShowDirectionsView();
                }
                else
                {
                    CalculateRouteWithCoordinates(shortTourList);
                }

                CreateNewPushpinForTourLocations(shortTourList);

            }
            else
            {
                if (compelteTourResult != null)
                {//Toggle from short version to complete version
                    // Create a new route based on route calculator result,
                    // and add the new route to the route collection.
                    routeModel = new RouteModel(compelteTourResult.routePoints);
                    // Add new route itineraries to the itineraries collection.
                    foreach (var itineraryItem in compelteTourResult.routeItenaries[0].Itinerary)
                    {
                        Itineraries.Add(itineraryItem);
                    }

                    Routes.Add(routeModel);
                    // Set the map to center on the new route.
                    //TODO : Change this to point to the start location of the tour
                    var viewRect = LocationRect.CreateLocationRect(routeModel.Locations);
                    Map.SetView(viewRect);

                    //ShowDirectionsView();
                }
                else
                {
                    CalculateRouteWithCoordinates(coordinateList);
                }
                CreateNewPushpinForTourLocations(coordinateList);
            }

           //After the route is drawn, Add pushpins to the locations
            
           */
        }

        private void ButtonDirections_Click(object sender, EventArgs e)
        {
            // Display or hide directions panel.
            if (_visualStates.DirectionsState == VisualStates.HideDirections)
            {
                if (HasDirections)
                {
                    _visualStates.DirectionsState = VisualStates.ShowDirections;
                }
            }
            else
            {
                _visualStates.DirectionsState = VisualStates.HideDirections;
            }

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void ButtonMode_Click(object sender, EventArgs e)
        {
            ChangeMapMode();

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void touchBehavior_Tap(object sender, TouchBehaviorEventArgs e)
        {
            // Hide pushpins panel.
           // _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void touchBehavior_Move(object sender, TouchBehaviorEventArgs e)
        {
            // Hide pushpins panel.
           // _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void touchBehavior_Hold(object sender, TouchBehaviorEventArgs e)
        {
           // CenterPushpinsPopup(e.TouchPoint);

            // Show pushpins panel.
          //  _visualStates.PushpinsState = VisualStates.ShowPushpins;
        }

        //Retrieve the passed data 

        // When page is navigated to set data context to selected item in list
        private string tourId = null;
        private Expression.Blend.SampleData.ottawaSampleDataSource.tour selectedTour = null;
        private Expression.Blend.SampleData.ottawaSampleDataSource.stop selectedStop = null;
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            string s = "";

            //clear all the stored values
            shortTourList.Clear();
            coordinateList.Clear();

            if (NavigationContext.QueryString.TryGetValue("tourIndex", out s))
            {
                tourId = s;
                var tours = (Expression.Blend.SampleData.ottawaSampleDataSource.toursList)App.Current.Resources["OttawaSampleDataSource"];
                //Get the selected tour inforamtion from the id
                //Iterate through the collection
               
                foreach (var tour in tours.tourCollection)
                {
                    if (tour.id.Equals(tourId))
                    {
                        selectedTour = tour;
                        break;
                    }
                }

                if (selectedTour == null) return;

                //Get the stops collection
                var stopsCollection = selectedTour.stopCollection;
                List<string> locationCollection = new List<string>();
               

                foreach (var stop in stopsCollection)
                {
                    location stopLocation = stop.location;
                    locationCollection.Add(stopLocation.latitude + "$" + stopLocation.longitude);
                    
                }

                string[] locationArray = locationCollection.ToArray();

                //sort the locations based on distance and find the nearest one to the user and next one to that
               // TODO : CHeck this  
                //Add the user current location 
                shortTourList.Add(userCurrentLocationLatitide + "$" + userCurrentLocationLongitude);

                //Among the tour list find the one nearest to the user
                double distance = -1;
                int index = 0;
                GeoCoordinate userLocation = new GeoCoordinate(userCurrentLocationLatitide, userCurrentLocationLongitude);
                
                //find the one nearest to the user
                for (int i = 0; i < locationArray.Length; i++)
                {

                    if (locationArray[i] != null)
                    {
                        //parse the data
                        double lat = double.Parse(locationArray[i].Split('$')[0]);
                        double lon = double.Parse(locationArray[i].Split('$')[1]);
                        GeoCoordinate tourLocation = new GeoCoordinate(lat, lon);
                        double tempDist = userLocation.GetDistanceTo(tourLocation);

                        //Now travel thru all the other points to find the nearest one

                        if (distance == -1 || distance > tempDist)
                        {
                            distance = tempDist;
                            index = i;
                            
                        }

                    }
                }

                //Swap the value
                string temp = locationArray[index];
                locationArray[index] = locationArray[0];
                locationArray[0] = temp;
               

                string[] sortedLocationArray = (sortRouteBasedonDistance(locationArray));

                shortTourList.AddRange(sortedLocationArray);
                //shortTourList.AddRange(locationArray);

                

                // tourPoints = sortRouteBasedonDistance(tourPoints);
                //TODO : temporarily storing all the sorted points only for debugging
                //coordinateList.AddRange(tourPoints);
                coordinateList.AddRange(shortTourList);

                if (toggleCompleteTour)
                {
                    // to calcualte with address
                    CalculateRouteWithCoordinates(shortTourList);

                }
                else
                {
                    CalculateRouteWithCoordinates(coordinateList);
                }


                // CalculateRouteWithCoordinates();

                // Hide pushpins panel.
                _visualStates.PushpinsState = VisualStates.HidePushpins;

                double latitude = double.Parse(locationArray[0].Split('$')[0]);
                double longitude = double.Parse(locationArray[0].Split('$')[1]);
                DefaultLocation = new GeoCoordinate(latitude, longitude);
            }

        }

        

        private string[] createShortTourRoute(string[] tourPoints)
        {
            string[] sortedTourPoints = new string[2];
            if (tourPoints != null && tourPoints.Length > 0)
            {

                if (tourPoints.Length == 1)
                {
                    return sortedTourPoints;
                }
                else
                {
                    double distance = -1;
                    int index = 0;
                    GeoCoordinate userLocation = new GeoCoordinate(userCurrentLocationLatitide, userCurrentLocationLongitude);
                    GeoCoordinate nearestTourLocation = userLocation;
                    //find the one nearest to the user
                    for (int i = 0; i < tourPoints.Length; i++)
                    {
                       
                        if (tourPoints[i] != null)
                        {
                            //parse the data
                            double latitude = double.Parse(tourPoints[i].Split('$')[0]);
                            double longitude = double.Parse(tourPoints[i].Split('$')[1]);
                            GeoCoordinate tourLocation = new GeoCoordinate(latitude, longitude);
                            double tempDist = userLocation.GetDistanceTo(tourLocation);

                            //Now travel thru all the other points to find the nearest one

                            if (distance == -1 || distance > tempDist)
                            {
                                distance = tempDist;
                                index = i;
                                nearestTourLocation = tourLocation;
                            }
                            
                        }
                    }
                    sortedTourPoints[0] = tourPoints[index];

                    int indexNotToInclude = index;
                    distance = -1;
                    index = 0;
                    //find the next sortest tour point
                    for (int i = 0; i < tourPoints.Length ; i++)
                    {
                        if (i == indexNotToInclude)
                            continue;

                        if (tourPoints[i] != null)
                        {
                            //parse the data
                            double latitude = double.Parse(tourPoints[i].Split('$')[0]);
                            double longitude = double.Parse(tourPoints[i].Split('$')[1]);
                            GeoCoordinate tourLocation = new GeoCoordinate(latitude, longitude);
                            double tempDist = nearestTourLocation.GetDistanceTo(tourLocation);

                            //Now travel thru all the other points to find the nearest one

                            if (distance == -1 || distance > tempDist)
                            {
                                distance = tempDist;
                                index = i;
                            }

                        }
                    }
                    sortedTourPoints[1] = tourPoints[index];
                }
            }

            return sortedTourPoints;
        }

        private string[] sortRouteBasedonDistance(string[] tourPoints)
        {
            string[] sortedTourPoints = tourPoints;
            if (tourPoints != null && tourPoints.Length > 0)
            {

                if (tourPoints.Length == 1)
                {
                    return sortedTourPoints;
                }
                else
                {
                    for (int i = 0; i < tourPoints.Length - 1; i++)
                    {
                        if (tourPoints[i] != null)
                        {
                            //parse the data
                            double latitude = double.Parse(tourPoints[i].Split('$')[0]);
                            double longitude = double.Parse(tourPoints[i].Split('$')[1]);

                            double distance = -1;
                            int index = 0;
                            //Now travel thru all the other points to find the nearest one
                            for (int j = i + 1; j < tourPoints.Length; j++)
                            {

                                if(tourPoints[i] != null)
                                {
                                    //parse the data
                                    double tempLatitude = double.Parse(tourPoints[j].Split('$')[0]);
                                    double tempLongitude = double.Parse(tourPoints[j].Split('$')[1]);
                                    
                                    var myLocation = new GeoCoordinate(tempLatitude,tempLongitude);
                                    var yourLocation = new GeoCoordinate(latitude, longitude);
                                    double tempDist = myLocation.GetDistanceTo(yourLocation);

                                    if (distance == -1 || distance > tempDist)
                                    {
                                        distance = tempDist;
                                        index = j;
                                    }
                                }
                            }

                            //swap the places
                            string temp = sortedTourPoints[i + 1];
                            sortedTourPoints[i + 1] = sortedTourPoints[index];
                            sortedTourPoints[index] = temp;

                           // tourPoints[i] = null;
                        }
                       
                                            
                    }
                }
            }

            return sortedTourPoints;

        }

        private int stopIndex;
        private void ButtonGo_Click(object sender, RoutedEventArgs e)
        {
            if (_visualStates.RouteState != VisualStates.HideRoute)
            {
                _visualStates.RouteState = VisualStates.HideRoute;
            }

            if(selectedPushPin == null) return;

            TextBlock content = selectedPushPin.Content as TextBlock;

            stopIndex = int.Parse(content.Text);
            
            //Since the user location is also counted in the list we reduce the number by 1

            stopIndex--;

            //Navigate to details page
            if (tourId != null && stopIndex >= 0)
            {

                //Navigate to details page and inform the selection
                NavigationService.Navigate(new Uri("/StopDetailsPage_new.xaml?tourIndex=" + tourId + "&stopIndex=" + stopIndex, UriKind.Relative));
                
                
            }
        }

        private void ButtonZoomIn_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Zoom += 1;

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void ButtonZoomOut_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            Zoom -= 1;

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }

        private void ListBoxPushpinCatalog_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var selector = sender as Selector;
            if (selector == null || selector.SelectedItem == null)
            {
                return;
            }

            CreateNewPushpin(selector.SelectedItem, _touchBehavior.LastTouchPoint);

            // Reset the selected item so we can pick it again next time.
            selector.SelectedItem = null;

            // Hide pushpins panel.
            _visualStates.PushpinsState = VisualStates.HidePushpins;
        }



        private void DirectionSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBox directionListBox = sender as ListBox;

            DirectionModel directionInfo = directionListBox.SelectedItem as DirectionModel;

            Rectangle loc = directionInfo.BoundingRectangle;

            Map.SetView(loc);

        }


        #endregion

        #region Privates

        /// <summary>
        /// Hides the route view and display the directions view.
        /// </summary>
        private void ShowDirectionsView()
        {
            _visualStates.RouteState = VisualStates.HideRoute;

            if (HasDirections)
            {
                _visualStates.DirectionsState = VisualStates.ShowDirections;
            }
        }

        #endregion

        #region Property Changed

        private void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
        {
        	// TODO: Add event handler implementation here.
			 _visualStates.RouteState = VisualStates.HideRoute;
             
        }

        private bool FollowUser = true;
        private void ApplicationBarMenuItem_Click(object sender, System.EventArgs e)
        {
            var menuItem = sender as Microsoft.Phone.Shell.ApplicationBarMenuItem;
            //Follow me is clicked, start drawing the route followed by the user.
            FollowUser = !FollowUser;

            if (FollowUser)
            {
                if (menuItem != null)
                    menuItem.Text = "Stop Following Me!";
            }
            else
            {
                //traceUserRoute.Clear();
                if (menuItem != null)
                    menuItem.Text = "Follow ME !";
            }
            
            
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        #endregion

        #region Visual States
        /// <summary>
        /// An internal helper class for handling MainPage visual state transitions.
        /// </summary>
        private class VisualStates
        {
            #region Predefined Visual States
            // Route States
            public const string ShowRoute = "ShowRoute";
            public const string HideRoute = "HideRoute";

            // Directions States
            public const string ShowDirections = "ShowDirections";
            public const string HideDirections = "HideDirections";

            // Pushpins States
            public const string ShowPushpins = "ShowPushpins";
            public const string HidePushpins = "HidePushpins";
            #endregion

            #region Fields
            private readonly Control _control;
            private string _routeState = VisualStates.HideRoute;
            private string _directionsState = VisualStates.HideDirections;
            private string _pushpinsState = VisualStates.HidePushpins;
            #endregion

            #region Properties
            /// <summary>
            /// Change the route panel visual state.
            /// </summary>
            public string RouteState
            {
                get { return _routeState; }
                set
                {
                    if (_routeState != value)
                    {
                        _routeState = value;
                        VisualStateManager.GoToState(_control, value, true);
                    }
                }
            }

            /// <summary>
            /// Change the directions panel visual state.
            /// </summary>
            public string DirectionsState
            {
                get { return _directionsState; }
                set
                {
                    if (_directionsState != value)
                    {
                        _directionsState = value;
                        VisualStateManager.GoToState(_control, value, true);
                    }
                }
            }

            /// <summary>
            /// Change the pushpins popup visual state.
            /// </summary>
            public string PushpinsState
            {
                get { return _pushpinsState; }
                set
                {
                    if (_pushpinsState != value)
                    {
                        _pushpinsState = value;
                        VisualStateManager.GoToState(_control, value, true);
                    }
                }
            }
            #endregion

            #region Ctor
            /// <summary>
            /// Initializes a new instance of this class.
            /// </summary>
            /// <param name="control">The target control.</param>
            public VisualStates(Control control)
            {
                _control = control;
            }
            #endregion
        }
        #endregion
    }

    public class RouteViewDataContext : INotifyPropertyChanged
    {
        private string _thumbNailUri;
        public string ThumbNailUri
        {
            get
            {
                return _thumbNailUri;
            }

            set
            {
                if (!value.Equals(_thumbNailUri))
                {
                    _thumbNailUri = value;
                    NotifyPropertyChanged("ThumbNailUri");
                }

                }
            }
           

        private string _text;
        public string Text
        {
            get
            {
                return _text;
            }

            set
            {
                if (!value.Equals(_text))
                {
                    _text = value;
                    NotifyPropertyChanged("Text");
                }

                }
            }

        private void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        }
        
    
}
